/*
 * yauosk - Yet Another Useless Operating System Kernel
 *
 * Copyright (c) 2009-2010 Matteo Cicuttin
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 * derived from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef _MACHINE_H_
#define _MACHINE_H_

#include <arch/x86/asm.h>
#include <arch/x86/mmu.h>
#include <sys/types.h>

#define MP_ENTRY 0x7000
/*
struct pgtbl_entry {
	uint p : 1;
	uint rw : 1;
	uint us : 1;
	uint rsv0 : 2;
	uint a : 1;
	uint d : 1;
	uint rsv1 : 2;
	uint avail : 3;
	uint pfa : 20;
};
 */

#define	PAGESIZE	4096	/* Should be moved in arch/x86/machine.h */

void	biostty_init(void);
void	biostty_putc(int);
#define PUTC(x) biostty_putc(x)

void x86_dump_registers(void);
void x86_dump_page_dir_entry(int entry);



/* After a trap the stack appears as this structure */
struct trapframe {
	/* Stuff pushed by pusha */
	uint edi;
	uint esi;
	uint ebp;
	uint _esp;
	uint ebx;
	uint edx;
	uint ecx;
	uint eax;
	
	/* rest of trap frame */
	ushort es;
	ushort padding1;
	ushort ds;
	ushort padding2;
	uint trapno;
	
	/* These are pushed by the hardware */
	uint err;
	uint eip;
	ushort cs;
	ushort padding3;
	uint eflags;
	
	/* These are useful when there is a switch between rings */
	uint esp;
	ushort ss;
	ushort padding4;
};





typedef enum {
	TRAP_DIVIDE =		0,
	TRAP_DEBUG =		1,
	TRAP_NMI =			2,
	TRAP_BREAKPOINT	=	3,
	TRAP_OVERFLOW =		4,
	TRAP_BOUNDCHK =		5,
	TRAP_ILLEGAL_OP =	6,
	TRAP_DEVICE =		7,
	TRAP_DOUBLE_FAULT =	8,
	TRAP_COPROCESSOR =	9,
	TRAP_INVALID_TSS =	10,
	TRAP_NO_SEGMENT =	11,
	TRAP_STACK =		12,
	TRAP_GPF =			13,
	TRAP_PAGE_FAULT	=	14,
	TRAP_RESERVED =		15,
	TRAP_FPEX =			16,
	TRAP_ALIGNMENT =	17,
	TRAP_MCE =			18,
	TRAP_SIMDERR =		19,

	TRAP_SYSCALL =		128,	/* 0x80 */
} trap_t;

/* Interrupts */
#define IRQ_OFFSET 32		/* Interrupts are mapped starting at trap 32 */

typedef enum {
	IRQ_TIMER =			0,
	IRQ_KEYBOARD =		1,
	IRQ_CASCADE =		2,
	IRQ_COM2 =			3,
	IRQ_COM1 =			4,
	IRQ_FLOPPY =		6,
	IRQ_LPT =			7,
	IRQ_RTC	=			8,
	IRQ_PRI_IDE =		14,
	IRQ_SEC_IDE	=		15,
	IRQ_ERROR =         19,
	IRQ_SPURIOUS =      31,
} irq_t;

void trap_init(void);
void trap_install_handler(trap_t, void (*)(void));
void trap_remove_handler(trap_t);
void irq_install_handler(irq_t, void (*)(void));
void irq_remove_handler(irq_t);

/*
 * SMP-related stuff
 */
extern uint lapicaddr;
extern uint smp_num_cpus;
extern uint sys_maxbus;
extern uint sys_apics;
extern uint sys_ints;
extern uint bsp_id;
extern uint sys_is_smp;

#define MAXPE	255
#define	MAXBE	32
#define	MAXAPIC	255
#define	MAXINTR	255
#define BOOTSTKSIZE	512

#define GDT_ENTRIES	8

struct cpu
{
	struct segdescr		gdt[GDT_ENTRIES];
	u_int8_t			id;
	volatile u_int8_t	online;
	u_int8_t			stack[BOOTSTKSIZE];
};

extern struct cpu cpu[MAXPE];

#endif /* _MACHINE_H_ */